From: iap10@labyrinth.cl.cam.ac.uk Date: Sat, 1 May 2004 00:30:43 +0000 (+0000) Subject: bitkeeper revision 1.882 (4092efb3iUwNww3oOZDLfH3rovuyhg) X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~18239 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=418f1d43605265582e288ea855db9b25eefee900;p=xen.git bitkeeper revision 1.882 (4092efb3iUwNww3oOZDLfH3rovuyhg) suspend uses new batched getpageinfo interface --- diff --git a/tools/examples/xc_dom_control.py b/tools/examples/xc_dom_control.py index 080af6f366..4f0bd5de52 100755 --- a/tools/examples/xc_dom_control.py +++ b/tools/examples/xc_dom_control.py @@ -137,7 +137,10 @@ elif cmd == 'suspend': os.kill(pid, signal.SIGTERM) xc.domain_stop( dom=dom ) - time.sleep(0.1); + + while not xc.domain_getinfo( first_dom=dom, max_doms=1 )[0]['stopped']: + time.sleep(0.1); + rc = xc.linux_save( dom=dom, state_file=file, progress=1) if rc == 0 : xc.domain_destroy( dom=dom, force=1 ) diff --git a/tools/xc/lib/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c index 0a367234de..fb6fbd6f57 100644 --- a/tools/xc/lib/xc_linux_save.c +++ b/tools/xc/lib/xc_linux_save.c @@ -10,6 +10,8 @@ #include #include +#define BATCH_SIZE 512 /* 1024 pages (4MB) at a time */ + /* This may allow us to create a 'quiet' command-line option, if necessary. */ #define verbose_printf(_f, _a...) \ do { \ @@ -38,33 +40,7 @@ _res; \ }) -static int check_pfn_ownership(int xc_handle, - unsigned long mfn, - u64 dom) -{ - dom0_op_t op; - op.cmd = DOM0_GETPAGEFRAMEINFO; - op.u.getpageframeinfo.pfn = mfn; - op.u.getpageframeinfo.domain = (domid_t)dom; - return (do_dom0_op(xc_handle, &op) >= 0); -} -#define GETPFN_ERR (~0U) -static unsigned int get_pfn_type(int xc_handle, - unsigned long mfn, - u64 dom) -{ - dom0_op_t op; - op.cmd = DOM0_GETPAGEFRAMEINFO; - op.u.getpageframeinfo.pfn = mfn; - op.u.getpageframeinfo.domain = (domid_t)dom; - if ( do_dom0_op(xc_handle, &op) < 0 ) - { - PERROR("Unexpected failure when getting page frame info!"); - return GETPFN_ERR; - } - return op.u.getpageframeinfo.type; -} static int checked_write(gzFile fd, void *buf, size_t count) { @@ -281,28 +257,59 @@ int xc_linux_save(int xc_handle, /* - * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this - * loop we have each MFN mapped at most once. Note that there may be MFNs - * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP. + * Quick sanity check. */ for ( i = 0; i < srec.nr_pfns; i++ ) { mfn = live_pfn_to_mfn_table[i]; -#if 1 /* XXX use the master mfn_to_pfn table???? */ - - if( live_mfn_to_pfn_table[mfn] != i ) printf("i=%d mfn=%d live_mfn_to_pfn_table=%d\n", i,mfn,live_mfn_to_pfn_table[mfn]); + } - /* Query page type by MFN, but store it by PFN. */ - if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn, domid)) == - GETPFN_ERR ) - goto out; -#endif +/* test new pfn_type stuff */ + { + int n, i, j; + + if ( mlock( pfn_type, srec.nr_pfns * sizeof(unsigned long) ) ) + { + ERROR("Unable to mlock"); + goto out; + } + for ( n = 0; n < srec.nr_pfns; ) + { + + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) + { + pfn_type[i] = live_pfn_to_mfn_table[i]; + } + + if ( get_pfn_type_batch(xc_handle, domid, j, &pfn_type[n]) ) + { + ERROR("get_pfn_type_batch failed"); + goto out; + } + + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) + { + + pfn_type[i] >>= 29; + + if(pfn_type[i] == 7) + { + ERROR("bogus page"); + goto out; + } + +/* if(pfn_type[i]) + printf("i=%d type=%d\n",i,pfn_type[i]); */ + } + + n+=j; + } } @@ -354,13 +361,6 @@ int xc_linux_save(int xc_handle, goto out; } - /* Belts and braces safety check on the shared info record */ - if ( !check_pfn_ownership(xc_handle, shared_info_frame, domid) ) - { - ERROR("Invalid shared_info_frame"); - goto out; - } - if ( !checked_write(gfd, "LinuxGuestRecord", 16) || !checked_write(gfd, name, sizeof(name)) || !checked_write(gfd, &srec.nr_pfns, sizeof(unsigned long)) || @@ -376,8 +376,6 @@ int xc_linux_save(int xc_handle, verbose_printf("Saving memory pages: 0%%"); -#define BATCH_SIZE 1024 /* 1024 pages (4MB) at a time */ - if ( (mapper_handle2 = mfn_mapper_init(xc_handle, domid, BATCH_SIZE*4096, PROT_READ )) == NULL ) diff --git a/tools/xc/lib/xc_private.c b/tools/xc/lib/xc_private.c index 0c9092b607..d137176ca8 100644 --- a/tools/xc/lib/xc_private.c +++ b/tools/xc/lib/xc_private.c @@ -168,29 +168,7 @@ void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, /*******************/ -typedef struct dom0_op_compact_getpageframeinfo { - unsigned long cmd; - unsigned long interface_version; /* DOM0_INTERFACE_VERSION */ - dom0_getpageframeinfo_t getpageframeinfo; -} dom0_op_compact_getpageframeinfo_t; - - -typedef struct mfn_typer { - domid_t dom; - int max; - int nr_multicall_ents; - multicall_entry_t *multicall_list; - dom0_op_compact_getpageframeinfo_t *gpf_list; -} mfn_typer_t; - - -mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ); - -void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn ); - -int mfn_typer_flush_queue(mfn_typer_t *t); - -unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx); +#if 0 mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ) { @@ -199,8 +177,8 @@ mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ) dom0_op_compact_getpageframeinfo_t *d; t = calloc(1, sizeof(mfn_typer_t) ); - m = calloc(1, sizeof(multicall_entry_t)*num ); - d = calloc(1, sizeof(dom0_op_compact_getpageframeinfo_t)*num ); + m = calloc(num, sizeof(multicall_entry_t)); + d = calloc(num, sizeof(dom0_op_compact_getpageframeinfo_t)); if (!t || !m || !d) { @@ -210,6 +188,16 @@ mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ) return NULL; } +printf("sizeof(m)=%d sizeof(d)=%d m=%p d=%p\n",sizeof(multicall_entry_t), sizeof(dom0_op_compact_getpageframeinfo_t),m,d); + + if ( (mlock(m, sizeof(multicall_entry_t)*num ) != 0) || + (mlock(d, sizeof(dom0_op_compact_getpageframeinfo_t)*num ) != 0) ) + { + PERROR("Could not lock memory for Xen hypercall"); + return NULL; + } + + t->xc_handle = xc_handle; t->max = num; t->nr_multicall_ents=0; t->multicall_list=m; @@ -229,7 +217,7 @@ void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn ) d->interface_version = DOM0_INTERFACE_VERSION; d->getpageframeinfo.pfn = mfn; d->getpageframeinfo.domain = t->dom; - d->getpageframeinfo.type = ~0UL; + d->getpageframeinfo.type = 1000; //~0UL; m->op = __HYPERVISOR_dom0_op; m->args[0] = (unsigned long)d; @@ -240,7 +228,7 @@ void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn ) int mfn_typer_flush_queue(mfn_typer_t *t) { if (t->nr_multicall_ents == 0) return 0; - (void)HYPERVISOR_multicall(t->multicall_list, t->nr_multicall_ents); + do_multicall_op(t->xc_handle, t->multicall_list, t->nr_multicall_ents); t->nr_multicall_ents = 0; } @@ -249,6 +237,38 @@ unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx) return t->gpf_list[idx].getpageframeinfo.type; } +#endif + +/* NB: arr must be mlock'ed */ + +int get_pfn_type_batch(int xc_handle, + u64 dom, int num, unsigned long *arr) +{ + dom0_op_t op; + op.cmd = DOM0_GETPAGEFRAMEINFO2; + op.u.getpageframeinfo2.domain = (domid_t)dom; + op.u.getpageframeinfo2.num = num; + op.u.getpageframeinfo2.array = arr; + return do_dom0_op(xc_handle, &op); +} + +#define GETPFN_ERR (~0U) +unsigned int get_pfn_type(int xc_handle, + unsigned long mfn, + u64 dom) +{ + dom0_op_t op; + op.cmd = DOM0_GETPAGEFRAMEINFO; + op.u.getpageframeinfo.pfn = mfn; + op.u.getpageframeinfo.domain = (domid_t)dom; + if ( do_dom0_op(xc_handle, &op) < 0 ) + { + PERROR("Unexpected failure when getting page frame info!"); + return GETPFN_ERR; + } + return op.u.getpageframeinfo.type; +} + /*******************/ diff --git a/tools/xc/lib/xc_private.h b/tools/xc/lib/xc_private.h index 198c703eaf..eaa301772d 100644 --- a/tools/xc/lib/xc_private.h +++ b/tools/xc/lib/xc_private.h @@ -110,6 +110,27 @@ static inline int do_dom0_op(int xc_handle, dom0_op_t *op) out1: return ret; } +static inline int do_multicall_op(int xc_handle, + void *call_list, int nr_calls) +{ + int ret = -1; + privcmd_hypercall_t hypercall; + + hypercall.op = __HYPERVISOR_multicall; + hypercall.arg[0] = (unsigned long)call_list; + hypercall.arg[1] = (unsigned long)nr_calls; + + if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 ) + { + if ( errno == EACCES ) + fprintf(stderr, "Dom0 operation failed -- need to" + " rebuild the user-space tool set?\n"); + goto out1; + } + + out1: return ret; +} + static inline int do_network_op(int xc_handle, network_op_t *op) { int ret = -1; @@ -222,5 +243,31 @@ int mfn_mapper_flush_queue(mfn_mapper_t *t); void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, unsigned long mfn, int size ); +/*********************/ + + +#if 0 +typedef struct mfn_typer { + domid_t dom; + int xc_handle; + int max; + dom0_op_t op; +} mfn_typer_t; + + +mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ); + +void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn ); + +int mfn_typer_flush_queue(mfn_typer_t *t); +#endif + +int get_pfn_type_batch(int xc_handle, + u64 dom, int num, unsigned long *arr); + +unsigned int get_pfn_type(int xc_handle, + unsigned long mfn, + u64 dom); + #endif /* __XC_PRIVATE_H__ */ diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index c6ca8149c6..ef0ab2e81b 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -564,6 +564,84 @@ long do_dom0_op(dom0_op_t *u_dom0_op) } break; + case DOM0_GETPAGEFRAMEINFO2: + { +#define GPF2_BATCH 128 + int n,j; + int num = op->u.getpageframeinfo2.num; + domid_t dom = op->u.getpageframeinfo2.domain; + unsigned long *s_ptr = (unsigned long*) op->u.getpageframeinfo2.array; + struct task_struct *p; + unsigned long l_arr[GPF2_BATCH]; + ret = -ESRCH; + + if ( unlikely((p = find_domain_by_id(dom)) == NULL) ) + break; + + if ( unlikely(num>1024) ) + { + ret = -E2BIG; + break; + } + + ret = 0; + for(n=0;nGPF2_BATCH)?GPF2_BATCH:(num-n); + + if( copy_from_user( l_arr, &s_ptr[n], k*sizeof(unsigned long) ) ) + { + ret = -EINVAL; + break; + } + + for(j=0;j= max_page) ) + goto e2_err; + + page = &frame_table[mfn]; + + if ( likely(get_page(page, p)) ) + { + unsigned long type = 0; + switch( page->type_and_flags & PGT_type_mask ) + { + case PGT_l1_page_table: + case PGT_l2_page_table: + case PGT_l3_page_table: + case PGT_l4_page_table: + type = page->type_and_flags & PGT_type_mask; + + } + l_arr[j] |= type; + put_page(page); + } + else + { + e2_err: + l_arr[j] |= PGT_type_mask; /* error */ + } + + } + + if( copy_to_user( &s_ptr[n], l_arr, k*sizeof(unsigned long) ) ) + { + ret = -EINVAL; + break; + } + + n+=j; + } + + put_task_struct(p); + + } + break; + default: ret = -ENOSYS; diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index e943338a0d..3bc18476af 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -266,6 +266,16 @@ typedef struct dom0_setdomainmaxmem_st unsigned int max_memkb; } dom0_setdomainmaxmem_t; +#define DOM0_GETPAGEFRAMEINFO2 29 /* batched interface */ +typedef struct dom0_getpageframeinfo2_st +{ + /* IN variables. */ + domid_t domain; /* To which domain do frames belong? */ + int num; + /* IN/OUT variables. */ + unsigned long *array; +} dom0_getpageframeinfo2_t; + typedef struct dom0_op_st { @@ -297,6 +307,7 @@ typedef struct dom0_op_st dom0_setdomainname_t setdomainname; dom0_setdomaininitialmem_t setdomaininitialmem; dom0_setdomainmaxmem_t setdomainmaxmem; + dom0_getpageframeinfo2_t getpageframeinfo2; } u; } dom0_op_t;